from django.shortcuts import render
from django.views import View
import json
from django import http
from qingmei_mall.utils.response_code import RETCODE
from goods.models import SKU
from django_redis import get_redis_connection
from qingmei_mall.utils import meiduo_json


# 购物车增删改查
class CartView(View):
    # 添加购物车
    def post(self, request):
        # 接收
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get("sku_id")
        count = json_dict.get("count")
        # 验证
        # 非空
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "参数不完整"})
        # sku_id是否有效
        try:
            sku = SKU.objects.get(id=sku_id)
        except:
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "无效的sku_id"})
        # 数量是否大于库存
        if count > sku.stock:
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "超过库存上限"})
        # 处理
        user = request.user
        # 创建响应对象
        response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
        # 判断用户是否登录
        if user.is_authenticated:
            # 已登陆，存redis
            """
            {
                cart_1:{
                    3:4,
                    4:2,
                    5:5,
                    ...
                }
            }

            """
            redis_cli = get_redis_connection("cart")
            key = "cart_%d" % user.id
            # 添加购物车信息
            redis_cli.hincrby(key, sku_id, count)
            # 添加选中状态
            redis_cli.sadd("selected_%d" % user.id, sku_id)

        else:
            # 未登陆，存cookie
            """
            {
            3:{
                count:3,
                selected:True
            },
            4:{
                count:1,
                selected:True
            },
            }
            """
            # 从cookie中读取购物车信息
            cart_info = request.COOKIES.get("cart")
            if cart_info:
                # 读到购物车数据
                # 将加密后的字符串转为字典
                cart_dict = meiduo_json.loads(cart_info)

                # 判断当前商品在不在cookie_dict中
                # 如果在则将数量累加
                if sku_id in cart_dict.keys():

                    cart_dict[sku_id]["count"] += count
                else:
                    # 向cookie中的购物车数据新增
                    cart_dict[sku_id] = {
                        "count": count,
                        "selected": True
                    }

            else:
                # 没有读到购物车数据
                cart_dict = {
                    sku_id: {
                        "count": count,
                        "selected": True
                    }
                }
            response.set_cookie("cart", meiduo_json.dumps(cart_dict), expires=60 * 60 * 5)
        # 响应
        return response

    # 展示购物车
    def get(self, request):
        # 处理
        cart_skus = []
        cart_dict = {}
        user = request.user
        # 已登录
        if user.is_authenticated:
            # 如果用户登陆从redis中查询
            # 从redis中查询购物车数据
            redis_cli = get_redis_connection("cart")
            key = "cart_%d" % user.id
            """{b'3': b'5', b'8': b'3'}"""
            # 购物车：库存商品id和对应的数量  [{3:6,5:2}
            sku_ids = redis_cli.hgetall(key)
            # 查看选中集合
            selectes = redis_cli.smembers("selected_%d" % user.id)

            """{b'11': b'1', b'13': b'3', b'7': b'1', b'3': b'1'}"""
            for sku_id, count in sku_ids.items():
                cart_dict[int(sku_id)] = {
                    "count": int(count),
                    "selected": sku_id in selectes
                }
        # 未登录
        else:
            # 未登陆从cookie中查数据
            cart_str = request.COOKIES.get("cart")
            if cart_str is not None:
                cart_dict = meiduo_json.loads(cart_str)
        # 遍历cart_dict
        for sku_id, info in cart_dict.items():
            # 根据id查询库存商品对象
            sku = SKU.objects.get(id=sku_id, is_launched=True)
            total_amount = sku.price * info["count"]
            cart_skus.append({
                "id": sku_id,
                "name": sku.name,
                "count": info["count"],
                "selected": str(info["selected"]),
                "default_image_url": sku.default_image.url,
                "price": str(sku.price),
                "total_amount": str(total_amount)
            })
        # 响应
        context = {
            'cart_skus': cart_skus,
        }
        return render(request, "cart.html", context)

    # 修改购物车
    def put(self, request):
        # 接收
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get("sku_id")
        count = json_dict.get("count")
        selected = json_dict.get("selected", True)
        # 验证
        # selected 未布尔值，不参与非空验证
        # 非空
        if not all([sku_id, count]):
            return http.JsonResponse({"code": RETCODE.PARAMERR, "errmsg": "参数不完整"})
        # sku_id是否有效
        try:
            sku = SKU.objects.get(id=sku_id)
        except:
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "无效的sku_id"})
        # 数量是否大于库存
        if count > sku.stock:
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "超过库存上限"})
        # 验证selected是否为布尔值
        if not isinstance(selected, bool):
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "无效的选中状态"})
        # 处理
        user = request.user
        if user.is_authenticated:
            # 如果用户已登陆，修改redis中的数据
            key = "cart_%d" % user.id
            redis_cli = get_redis_connection("cart")
            # 覆盖原有的数量
            redis_cli.hset(key, sku_id, count)

            # 修改选中状态
            if selected:
                # 如果selected的值为True代表该库存商品要选中(追加到集合中)
                redis_cli.sadd("selected_%d" % user.id, sku_id)
            else:
                # 如果selected的值为False代表该库存商品要取消选中(从集合中删除)
                redis_cli.srem("selected_%d" % user.id, sku_id)
            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': str(selected),
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'total_amount': sku.price * count,
            }
            # 响应
            return http.JsonResponse(
                {
                    'code': RETCODE.OK,
                    'errmsg': 'OK',
                    'cart_sku': cart_sku
                }
            )

        else:
            # 如果用户未登陆，修改cookie
            # 获取cookie中的购物车数据
            cart_str = request.COOKIES.get("cart")
            # 判断有无购物车数据
            if cart_str:
                cart_dict = meiduo_json.loads(cart_str)
                # 读到了cookie
                # 覆盖原有数量
                cart_dict[sku_id]["count"] = count
                # 修改选中状态
                cart_dict[sku_id]["selected"] = selected
                cart_sku = {
                    'id': sku_id,
                    'count': count,
                    'selected': str(selected),
                    'name': sku.name,
                    'default_image_url': sku.default_image.url,
                    'price': sku.price,
                    'total_amount': sku.price * count,
                }
            else:
                # 读取不到cookie
                return http.JsonResponse({"code": RETCODE.PARAMERR, "errmsg": "无效的购物车数据"})

            return http.JsonResponse(
                {
                    'code': RETCODE.OK,
                    'errmsg': 'OK',
                    'cart_sku': cart_sku
                }
            )

    # 删除购物车
    def delete(self, request):
        # 接收
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get("sku_id")
        # 验证
        if not all([sku_id]):
            return http.JsonResponse({"code": RETCODE.PARAMERR, "errmsg": "参数不完整"})
        # sku_id是否有效
        try:
            sku = SKU.objects.get(id=sku_id)
        except:
            return http.JsonResponse({"code": RETCODE.PARAMERR, "error": "无效的sku_id"})
        # 处理
        response = http.JsonResponse({"code": RETCODE.OK, "errmsg": "ok"})
        user = request.user
        if user.is_authenticated:
            # 用户已登陆
            redis_cli = get_redis_connection("cart")
            redis_pl = redis_cli.pipeline()
            # 删除redis中hash的数据
            redis_pl.hdel("cart_%d" % user.id, sku_id)
            # 删除redis中set的数据
            redis_pl.srem("selected_%d" % user.id, sku_id)
            redis_pl.execute()
        else:
            # 用户未登陆
            cart_str = request.COOKIES.get("cart")
            cart_dict = meiduo_json.loads(cart_str)
            # 根据字典的键删除键值对
            del cart_dict[sku_id]
            cart_dict = meiduo_json.dumps(cart_dict)
            # 将删除后的数据重新写入cookie
            response.set_cookie("cart", cart_dict, expires=60 * 60 * 5)
        # 响应
        return response


# 全选购物车
class AllSelectView(View):
    def put(self, request):
        # 接收
        json_dict = json.loads(request.body.decode())
        selected = json_dict.get("selected", True)
        # 验证
        if not isinstance(selected, bool):
            return http.JsonResponse({"code": RETCODE.PARAMERR, "errmsg": "无效的选中状态"})
        # 处理
        user = request.user
        response = http.JsonResponse({"code": RETCODE.OK, "errmsg": "OK"})
        if user.is_authenticated:
            # 用户已登陆
            redis_cli = get_redis_connection("cart")
            # 如果selected值为True代表全部加入到集合中
            if selected:
                # 从hash中取出所有库存商品id 得到一个列表[b'5', b'3', b'11', b'13']
                sku_ids = redis_cli.hkeys("cart_%d" % user.id)
                # 将列表拆包传入sadd中
                redis_cli.sadd("selected_%d" % user.id, *sku_ids)
            # 如果selected值为False代表从集合中全部删除
            else:
                # 将选中状态的集合直接删掉
                redis_cli.delete("selected_%d" % user.id)
            pass
        else:
            pass
            # 用户未登陆
            # 查询cookie
            cart_str = request.COOKIES.get("cart")
            cart_dict = meiduo_json.loads(cart_str)
            # 全部选中
            if selected:
                for sku_id, info in cart_dict.items():
                    info["selected"] = selected

            # 全部取消选中
            else:
                for sku_id, info in cart_dict.items():
                    info["selected"] = selected
            cart_dict = meiduo_json.dumps(cart_dict)
            response.set_cookie("cart", cart_dict, expires=60 * 60 * 5)
        # 响应
        return response


# 简单购物车
class SimpleCartView(View):
    def get(self, request):
        user = request.user
        cart_dict = {}
        cart_skus = []
        # 用户登陆去redis中查询购物车信息
        if user.is_authenticated:
            redis_cli = get_redis_connection("cart")
            cart_dict = redis_cli.hgetall("cart_%d" % user.id)
            # for sku_id,count in cart_dict.items():
            #     cart_dict[int(sku_id)] = int(count)
            # 字典推导式
            cart_dict = {int(sku_id): int(count) for sku_id, count in cart_dict.items()}
            """
            {
                sku_id:count
            },{},{}
            """
        # 用户未登陆去cookie查询购物车信息
        else:
            cart_str = request.COOKIES.get("cart")
            cart_dict = meiduo_json.loads(cart_str)
            # 将cookie中的数据与redis中的数据统一，方便代码复用
            cart_dict = {int(sku_id): int(info["count"]) for sku_id, info in cart_dict.items()}
            """
            {
                sku_id:{
                    "count":2,
                    "selected":Trle
                }

            }

            """

        # 查询库存商品信息  [1,5,7,8]
        sku_ids = cart_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids, is_launched=True)
        for sku in skus:
            cart_skus.append({
                "id": sku.id,
                "name": sku.name,
                "count": cart_dict[sku.id],
                "default_image_url": sku.default_image.url
            })
        """
        "cart_skus":[
            {
                "id":1,
                "name":"Apple MacBook Pro 13.3英寸笔记本 银色",
                "count":1,
                "default_image_url":"http://image.qingmei.site:8888/group1/M00/00/02/CtM3BVrPB4GAWkTlAAGuN6wB9fU4220429"
            },
            ......
        ]

        """
        # 响应
        return http.JsonResponse({
            "code": RETCODE.OK,
            "errmsg": "OK",
            "cart_skus": cart_skus
        })






